/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package apresentacao;

import exception.MovimentoInvalidoException;
import exception.MovimentoPendenteException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import negocio.*;

/**
 *
 * @author luiz.oliveira
 */
public class Main {

	public static final int JOGAR = 1;
	public static final int ALTERAR_DADOS = 2;
	public static final int RANKING_10_POSITIVO = 3;
	public static final int RANKING_10_NEGATIVO = 4;
	public static final int INSERIR = 5;
	public static final int REMOVER = 6;
	public static final int SAIR = 0;
	public static Sistema sistema = new Sistema();
	public static Scanner entrada = new Scanner(System.in);

	public static void inserir() {
		String continuar;
		do {
			Jogador jogador = new Jogador();

			System.out.print("Nome: ");
			jogador.setNome(entrada.nextLine());
			System.out.print("Login: ");
			jogador.setLogin(entrada.nextLine());
			System.out.print("Senha: ");
			jogador.setPassword(entrada.nextLine());

			jogador.permissao.addPermissao(Permissao.JOGAR);

			try {
				sistema.jogadorDAO.store(jogador);

				System.out.print("Continuar inserindo(ENTER/N): ");
				continuar = entrada.nextLine();
			} catch (Exception e) {
				System.out.println(e.getMessage());
				continuar = null;
			}
		} while (continuar != null && !continuar.equalsIgnoreCase("N"));
	}

	public static void remover() {
		String login;
		Jogador jogador;

		do {
			System.out.print("Login(pressione ENTER para sair): ");
			login = entrada.nextLine();
			if (login.length() == 0) {
				break;
			}

			jogador = sistema.jogadorDAO.getByLogin(login);
			if (jogador == null) {
				System.out.println("Jogador não encontrado.");
			} else {
				String opcao;
				boolean invalido = false;
				do {
					System.out.print("Confirmar exclusão do jogador " + jogador.getNome() + "(S/N): ");
					opcao = entrada.nextLine();
					if (opcao.equalsIgnoreCase("S")) {
						sistema.jogadorDAO.removeByLogin(login);
						invalido = false;
					} else if (!opcao.equalsIgnoreCase("N")) {
						System.out.println("Opção inválida.");
						invalido = true;
					}
				} while (invalido);
			}
		} while (jogador == null);
	}

	public static void alterarDados() {
		boolean erro = true;

		do {
			System.out.print("Nome(pressione ENTER para permanecer " + sistema.jogador.getNome() + "): ");
			String nome = entrada.nextLine();
			if (nome.length() > 0) {
				sistema.jogador.setNome(nome);
			}
			System.out.print("Login(pressione ENTER para permancer " + sistema.jogador.getLogin() + "): ");
			String login = entrada.nextLine();
			if (login.length() > 0) {
				sistema.jogador.setLogin(login);
			}
			System.out.print("Senha(pressione ENTER para permancer a senha anterior): ");
			String password = entrada.nextLine();
			if (password.length() > 0) {
				sistema.jogador.setPassword(password);
			}

			try {
				sistema.jogadorDAO.store(sistema.jogador);
				System.out.println("Dados alterados com sucesso.");
				erro = false;
			} catch (Exception e) {
				System.out.println(e.getMessage());
				erro = true;
			}
		} while (erro);
	}

	public static void ranking(List<Jogador> list, int fromIndex, int posicaoInicial) {
		//Contagem de tamanho maximo de palavras
		int palavraMax = 0;
		int scoreMax = 0;
		for (Jogador jogador : list) {
			int palavraCurrent = jogador.getNome().length() + jogador.getLogin().length();
			int scoreCurrent = Integer.toString(jogador.getScore()).length();
			if (palavraCurrent > palavraMax) {
				palavraMax = palavraCurrent;
			}
			if (scoreCurrent > scoreMax) {
				scoreMax = scoreCurrent;
			}
		}

		String format = "%0" + Integer.toString(posicaoInicial + 10).length()
				+ "d: %-" + (palavraMax + 4) + "s %" + scoreMax + "s\n";

		int position = 0;
		int size = list.size();
		for (int i = fromIndex; i < size; i++) {
			Jogador jogador = list.get(i);
			if (position == 0 || list.get(i - 1).getScore() != jogador.getScore()) {
				position++;
			}
			if (position == 11) {
				break;
			}
			System.out.printf(format, posicaoInicial + position,
					jogador.getNome() + " (" + jogador.getLogin() + ")",
					jogador.getScore());
		}
	}

	public static void ranking10Positivo() {
		System.out.println("10 primeiros colocados:");

		ArrayList<Jogador> list = sistema.jogadorDAO.getList();
		EJogadorComparator jogadorComparator = EJogadorComparator.SCORE_POSITIVE;
		Collections.sort(list, jogadorComparator);

		ranking(list, 0, 0);
	}

	public static void ranking10Negativo() {
		System.out.println("10 últimos colocados:");

		ArrayList<Jogador> list = sistema.jogadorDAO.getList();
		EJogadorComparator jogadorComparator = EJogadorComparator.SCORE_POSITIVE;
		Collections.sort(list, jogadorComparator);

		int size = list.size();

		//Obtem o total de posicoes.
		int totalPosicao = 0;
		int i = 0;
		for (; i < size; i++) {
			if (totalPosicao == 0 || list.get(i - 1).getScore() != list.get(i).getScore()) {
				totalPosicao++;
			}
		}

		/**
		 * Verifica a partir de qual jogador começa os 10 últimos colocados.
		 * Observe que dois ou mais jogadores podem ocupar a mesma posicao.
		 * Portanto os 10 ultimos colocados podem ser mais de 10 jogadores.
		 *
		 */
		int position = 0;
		i = size - 1;
		for (; i >= 0; i--) {
			if (position == 0 || list.get(i + 1).getScore() != list.get(i).getScore()) {
				position++;
			}
			if (position == 11) {
				i++;
				break;
			}
		}

		ranking(list, i, totalPosicao - position + 1);
	}

	public static void main(String args[]) {
		//Introducao
		System.out.println("Damas\n\n");

		//Login
		String login1, login2, password;

		System.out.println("Jogador 1");
		String jogador1 = logar();
		if (jogador1 == null) {
			return;
		}

		//Menu
		System.out.println("Menu:");
		if (sistema.jogador.permissao.permite(Permissao.JOGAR)) {
			System.out.println(JOGAR + ": Jogar");
		}

		System.out.println(ALTERAR_DADOS + ": Alterar dados");
		System.out.println(RANKING_10_POSITIVO + ": 10 primeiros colocados");
		System.out.println(RANKING_10_NEGATIVO + ": 10 últimos colocados");
		if (sistema.jogador.permissao.permite(Permissao.ADMINISTRAR)) {
			System.out.println(INSERIR + ": Inserir jogador");
			System.out.println(REMOVER + ": Remover jogador");
		}
		System.out.println(SAIR + ": Sair");

		int opcao;

		System.out.print("Opção: ");
		try {
			opcao = Integer.parseInt(entrada.nextLine());
		} catch (Exception e) {
			opcao = -1;
		}

		while (opcao != SAIR) {
			switch (opcao) {
				case JOGAR:
					if (sistema.jogador.permissao.permite(Permissao.JOGAR)) {
						jogar(jogador1);
					} else {
						System.out.println("Você não tem permissão para visualizar esse menu.");
					}
					break;
				case ALTERAR_DADOS:
					alterarDados();
					break;
				case RANKING_10_POSITIVO:
					ranking10Positivo();
					break;
				case RANKING_10_NEGATIVO:
					ranking10Negativo();
					break;
				case INSERIR:
					if (sistema.jogador.permissao.permite(Permissao.ADMINISTRAR)) {
						inserir();
					} else {
						System.out.println("Você não tem permissão para visualizar esse menu.");
					}
					break;
				case REMOVER:
					if (sistema.jogador.permissao.permite(Permissao.ADMINISTRAR)) {
						remover();
					} else {
						System.out.println("Você não tem permissão para visualizar esse menu.");
					}
					break;
				default:
					System.out.println("Opção inválida.");
			}

			System.out.print("Opção: ");
			try {
				opcao = Integer.parseInt(entrada.nextLine());
			} catch (Exception e) {
				opcao = -1;
			}
		}
	}

	private static void jogar(String jogador1) {
		System.out.println("Jogador 2");
		String jogador2 = logar();

		Tabuleiro t = new Tabuleiro();
		System.out.println("O jogador " + jogador1 + " controlará as peças brancas.");

		String jogadorCorrente = jogador1;
		boolean posicaoInvalida = false;
		boolean desiste = false;
		Posicao proxima = null;
		Posicao atual = null;
		while (!t.acabou() && !desiste) {
			do {
				System.out.println(t);
				try {
					System.out.println("Jogador " + jogadorCorrente + " informe a peça a ser mexida, no formato x,y, ou D para desistir da partida:");
					String posicaoAtual = entrada.nextLine();
					if (posicaoAtual.equalsIgnoreCase("D")) {
						System.out.println("O jogador " + jogadorCorrente + " desistiu do jogo. A vitória foi para " + (jogadorCorrente.equals(jogador1) ? jogador2 : jogador1) + ".");
						sistema.salvarRanking((jogadorCorrente.equals(jogador1) ? jogador2 : jogador1));
						desiste = true;
						break;
					} else {
						System.out.println("Jogador " + jogadorCorrente + " informe a casa destino da peça, no formato x,y:");
						String posicaoProxima = entrada.nextLine();
						String[] pieces = posicaoAtual.split(",");
						String[] pieces2 = posicaoProxima.split(",");

						if (pieces.length != 2 || pieces2.length != 2) {
							System.out.println("Insira a posição da casa no formato x,y");
							posicaoInvalida = true;
						}

						atual = new Posicao(Integer.parseInt(pieces[0]), Integer.parseInt(pieces[1]));
						proxima = new Posicao(Integer.parseInt(pieces2[0]), Integer.parseInt(pieces2[1]));

						if (jogadorCorrente.equals(jogador1)) {
							t.mover(atual, proxima, ECor.BRANCO);
						} else {
							t.mover(atual, proxima, ECor.PRETO);
						}

						if (t.getTrocarJogador()) {
							jogadorCorrente = (jogadorCorrente.equals(jogador1) ? jogador2 : jogador1);
						}
					}
				} catch (NumberFormatException e) {
					posicaoInvalida = true;
					System.out.println("Insira a posição da casa no formato x,y");
				} catch (MovimentoInvalidoException e) {
					posicaoInvalida = true;
					System.out.println(e.getMessage());
				} catch (MovimentoPendenteException e) {
					posicaoInvalida = true;
					System.out.println(e.getMessage());
				} catch (Exception e) {
					System.out.println("Ocorreu um erro inesperado.");
				}
			} while (posicaoInvalida);
		}

		if (!desiste) {
			try {
				sistema.salvarRanking(jogadorCorrente);
			} catch (Exception e) {
				System.out.println("Ocorreu um erro inesperado ao salvar o ranking");
			}
		}
	}

	public static String logar() {
		System.out.print("Login: ");
		String login = entrada.nextLine();
		System.out.print("Senha: ");
		String password = entrada.nextLine();
		while (!sistema.login(login, password)) {
			System.out.println("Login ou senha incorreto.");
			System.out.print("Login(para sair pressione ENTER): ");
			login = entrada.nextLine();
			if (login.length() == 0) {
				return null;
			}
			System.out.print("Senha: ");
			password = entrada.nextLine();
		}
		return login;
	}
}